This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

source("tianfengRwrappers.R")
# library(future)
# plan("multiprocess",workers = 8)
CA_dataset2 <- readRDS("CA_dataset2.rds")
CA_dataset1 <- readRDS("CA_dataset1.rds")
human_coronary <- readRDS("human_coronary.rds")
Idents(human_coronary) <- human_coronary$samples
human_coronary <- RenameIdents(human_coronary,'1' = 'sample1','2' = 'sample2','3' = 'sample3','4' = 'sample4')
human_coronary$samples <- Idents(human_coronary)
Idents(human_coronary) <- human_coronary$Classification1
ds2 <- readRDS("ds2.rds")

#sample info

ggsave("dataset2_sampleinfo.svg",plot = umapplot(CA_dataset2, split.by = "sample"), 
       device = svg, width = 25, height = 5)
ggsave("dataset1_sampleinfo.svg",plot = umapplot(CA_dataset1, split.by = "orig.ident"),
       device = svg, width = 15, height = 5)
ggsave("dataset0_sampleinfo.svg",plot = umapplot(human_coronary, split.by = "samples"),
       device = svg, width = 20, height = 5)

附图:所有marker基因表达热图 show 表达量最高的top5

logfc.threshold = 0.5, min.diff.pct = 0.3 pct.1>0.7

dataset2

svg(paste0("CA_dataset2_supp","_markers.svg"), height = 10, width = 15)
dhm2(CA_dataset2_markers$gene, CA_dataset2, genes_to_show$gene,"CA_dataset2_supp")
dev.off()
null device 
          1 

dataset1

svg(paste0("CA_dataset1_supp","_markers.svg"), height = 10, width = 15)
dhm2(CA_dataset1_markers$gene, CA_dataset1, genes_to_show$gene,"CA_dataset1_supp")
dev.off()
null device 
          1 

dataset0

human_coronary_markers <- FindAllMarkers(human_coronary, logfc.threshold = 0.5, min.diff.pct = 0.3, only.pos = T)
Calculating cluster FB
Calculating cluster Macrophage
Calculating cluster EC
Calculating cluster SMC
Calculating cluster T cell
Calculating cluster B cell
Calculating cluster Neuron
Calculating cluster Plasma
human_coronary_markers <- human_coronary_markers[human_coronary_markers$pct.1>0.7,] %>% group_by(cluster) 

genes_to_show <- human_coronary_markers %>% group_by(cluster) %>% slice_max(n = 5, order_by = avg_logFC)

svg(paste0("human_coronary_supp","_markers.svg"), height = 10, width = 15)
dhm2(human_coronary_markers$gene, human_coronary, genes_to_show$gene,"human_coronary_supp")
dev.off()
RStudioGD 
        2 

样本细胞比例

Idents(human_coronary) <- human_coronary$conditions
sp1 <- subset(human_coronary, idents = "sample1")
sp2 <- subset(human_coronary, idents = "sample2")
sp3 <- subset(human_coronary, idents = "sample3")
sp4 <- subset(human_coronary, idents = "sample4")
prop_mat <- cbind(prop.table(table(sp1$Classification1)),prop.table(table(sp2$Classification1)))
prop_mat2 <- cbind(prop.table(table(sp3$Classification1)),prop.table(table(sp4$Classification1)))
prop_mat <- cbind(prop_mat, prop_mat2)
colnames(prop_mat) <- levels(Idents(human_coronary))


plot_data = melt(prop_mat)
colnames(plot_data) = c('cell type','position','proportion')#修改每一列的名称

ggplot(plot_data, aes(x = `cell type`, y = proportion, fill = position)) + 
  geom_bar(stat = 'identity', position = "dodge", width=0.5) + theme_bw()

prop_plot <- ggplot(plot_data, aes(x = `cell type`, y = proportion, fill = position)) + 
  geom_bar(stat = 'identity', position = "dodge", width=0.7) + coord_cartesian(ylim = c(0,0.3))+
  theme_bw() + scale_y_continuous(expand = c(0,0)) + scale_fill_manual(values = colors_list[3:6]) +theme(
    axis.title.x = element_text(size = 15), axis.text.x = element_text(size = 15, colour = "black"),
    axis.title.y = element_text(size = 15), axis.text.y = element_text(size = 15, colour = "black"),
    legend.text = element_text(size = 20), legend.title = element_blank(), panel.grid = element_blank())

ggsave("human_coronary_prop.svg", device = svg, plot = prop_plot, width = 12, height = 6)

XGBoost feature

pretrain AC–PA

fea <- read.csv("./datatable/AC_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds2_AC,labels = "",label = F)
ggsave("ACpretrain_features.png", device = png, plot = ggobj, width = 8, height = 8)

fea <- read.csv("./datatable/PA_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds2_PA,labels = "",label = F)
ggsave("PApretrain_features.png", device = png, plot = ggobj, width = 8, height = 8)

model AC–PA

fea <- read.csv("./datatable/ACtrain_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds2_AC,labels = "",label = F)
ggsave("ACmodel_features.png", device = png, plot = ggobj, width = 8, height = 8)

fea <- read.csv("./datatable/PAtrain_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds2_PA,labels = "",label = F)
ggsave("PAmodel_features.png", device = png, plot = ggobj, width = 8, height = 8)

model ds2

fea <- read.csv("./datatable/ds2_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds2,labels = "",label = F)
ggsave("ds2model_features.png", device = png, plot = ggobj, width = 8, height = 8)

fea <- read.csv("./datatable/ds0_features.csv")
ggobj <- multi_featureplot(fea$Feature[1:16],ds0,labels = "",label = F)
ggsave("ds0model_features.png", device = png, plot = ggobj, width = 8, height = 8)

scatter 比较 fig.3 DCN 和 LUM 在 FbM 中 sup vs unsup

ds2 -> ds0

bst_model <- readRDS("ds2_model.rds")
ds2_data <- get_data_table(ds2, highvar = F, type = "data")
Idents(ds2) <- ds2$seurat_clusters
Idents(ds0) <- ds0$seurat_clusters
temp <- get_data_table(ds0, highvar = F, type = "data")
ds0_data <- matrix(data=0, nrow = length(rownames(ds2_data)), ncol = length(colnames(temp)), 
                   byrow = FALSE, dimnames = list(rownames(ds2_data),colnames(temp)))
for(i in intersect(rownames(ds2_data), rownames(temp))){
  ds0_data[i,] <- temp[i,]
}
rm(temp)
ds0_label <- as.numeric(as.character(Idents(ds0)))
colnames(ds0_data) <- NULL
ds0_test_data <- list(data = t(as(ds0_data,"dgCMatrix")), label = ds0_label)
ds0_test <- xgb.DMatrix(data = ds0_test_data$data,label = ds0_test_data$label)

#预测结果
predict_ds0_test <- predict(bst_model, newdata = ds0_test)
predict_prop_ds0 <- matrix(data=predict_ds0_test, nrow = length(levels(Idents(ds2))), 
                           ncol = ncol(ds0), byrow = FALSE, 
                           dimnames = list(levels(Idents(ds2)),colnames(ds0)))

## 得到分群结果
ds0_res <- apply(predict_prop_ds0,2,func,rownames(predict_prop_ds0))
Idents(ds0) <- factor(ds0_res,levels = c(0:4))
umapplot(ds0)

ds0$supclustering <- Idents(ds0) #保存监督聚类结果
ggplot(data, aes(x=LUM, y=DCN, color = group, group = group)) +
  geom_point(size = 3) + 
  geom_smooth(method=lm , color="red", fill="#69b3a2", se=TRUE) +
  theme_classic() +  theme(axis.title = element_text(size = 20,color = "black"),
        axis.text = element_text(size = 20,color = "black"),
        axis.line = element_line(size = 1),
        axis.ticks = element_line(size = 1),
        title = element_text(size = 20))
`geom_smooth()` using formula 'y ~ x'

Idents(ds2) <- ds2$Classification1
ds2_SMC2 <- subset(ds2, ident = "SMC2")


data2 <- FetchData(object = ds2_SMC2, vars = c("ACTA2", "TAGLN"))
rownames(data2) <-  NULL
data2$group <- "unsup"

ggplot(data2, aes(x=ACTA2, y=TAGLN, color = group, group = group)) +
  geom_point(size = 3,alpha=0.1) + 
  geom_smooth(method=lm , color="red", fill="#69b3a2", formula = 'y~x', se=TRUE) +
  theme_classic() +  theme(axis.title = element_text(size = 20,color = "black"),
        axis.text = element_text(size = 20,color = "black"),
        axis.line = element_line(size = 1),
        axis.ticks = element_line(size = 1),
        title = element_text(size = 20))


data2 <- FetchData(object = ds2_SMC2, vars = c("SOST", "DLX5"))
rownames(data2) <-  NULL
data2$group <- "unsup"

ggplot(data2, aes(x=SOST, y=DLX5, color = group, group = group)) +
  geom_point(size = 3,alpha=0.1) + 
  geom_smooth(method=lm , color="red", fill="#69b3a2", formula = 'y~x', se=TRUE) +
  theme_classic() +  theme(axis.title = element_text(size = 20,color = "black"),
        axis.text = element_text(size = 20,color = "black"),
        axis.line = element_line(size = 1),
        axis.ticks = element_line(size = 1),
        title = element_text(size = 20))

# dim(subset(ds2_SMC2, SOST>0))[2]

dim(subset(ds2_SMC2, `DLX5`>1))[2]
[1] 503
dim(subset(ds2_SMC2, `DLX5`>1&SOST>1))[2]
[1] 261
print("...")
[1] "..."
dim(subset(ds2_SMC2, DLX5>1))[2]
[1] 503
dim(subset(ds2_SMC2, `PRDM6`>1))[2]
[1] 208
dim(subset(ds2_SMC2, `PRDM6`>1&DLX5>1))[2]
[1] 126
dim(subset(ds2_SMC2, ACTA2>1))[2]
[1] 792
dim(subset(ds2_SMC2, TAGLN>1))[2]
[1] 959
dim(subset(ds2_SMC2, TAGLN>1&ACTA2>1))[2]
[1] 781

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKYGBge3J9CnNvdXJjZSgidGlhbmZlbmdSd3JhcHBlcnMuUiIpCiMgbGlicmFyeShmdXR1cmUpCiMgcGxhbigibXVsdGlwcm9jZXNzIix3b3JrZXJzID0gOCkKYGBgCgpgYGB7cn0KQ0FfZGF0YXNldDIgPC0gcmVhZFJEUygiQ0FfZGF0YXNldDIucmRzIikKQ0FfZGF0YXNldDEgPC0gcmVhZFJEUygiQ0FfZGF0YXNldDEucmRzIikKaHVtYW5fY29yb25hcnkgPC0gcmVhZFJEUygiaHVtYW5fY29yb25hcnkucmRzIikKSWRlbnRzKGh1bWFuX2Nvcm9uYXJ5KSA8LSBodW1hbl9jb3JvbmFyeSRzYW1wbGVzCmh1bWFuX2Nvcm9uYXJ5IDwtIFJlbmFtZUlkZW50cyhodW1hbl9jb3JvbmFyeSwnMScgPSAnc2FtcGxlMScsJzInID0gJ3NhbXBsZTInLCczJyA9ICdzYW1wbGUzJywnNCcgPSAnc2FtcGxlNCcpCmh1bWFuX2Nvcm9uYXJ5JHNhbXBsZXMgPC0gSWRlbnRzKGh1bWFuX2Nvcm9uYXJ5KQpJZGVudHMoaHVtYW5fY29yb25hcnkpIDwtIGh1bWFuX2Nvcm9uYXJ5JENsYXNzaWZpY2F0aW9uMQpkczIgPC0gcmVhZFJEUygiZHMyLnJkcyIpCmBgYAoKI3NhbXBsZSBpbmZvCmBgYHtyfQpnZ3NhdmUoImRhdGFzZXQyX3NhbXBsZWluZm8uc3ZnIixwbG90ID0gdW1hcHBsb3QoQ0FfZGF0YXNldDIsIHNwbGl0LmJ5ID0gInNhbXBsZSIpLCAKICAgICAgIGRldmljZSA9IHN2Zywgd2lkdGggPSAyNSwgaGVpZ2h0ID0gNSkKZ2dzYXZlKCJkYXRhc2V0MV9zYW1wbGVpbmZvLnN2ZyIscGxvdCA9IHVtYXBwbG90KENBX2RhdGFzZXQxLCBzcGxpdC5ieSA9ICJvcmlnLmlkZW50IiksCiAgICAgICBkZXZpY2UgPSBzdmcsIHdpZHRoID0gMTUsIGhlaWdodCA9IDUpCmdnc2F2ZSgiZGF0YXNldDBfc2FtcGxlaW5mby5zdmciLHBsb3QgPSB1bWFwcGxvdChodW1hbl9jb3JvbmFyeSwgc3BsaXQuYnkgPSAic2FtcGxlcyIpLAogICAgICAgZGV2aWNlID0gc3ZnLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSA1KQoKYGBgCgoKIyDpmYTlm77vvJrmiYDmnIltYXJrZXLln7rlm6Dooajovr7ng63lm74gc2hvdyDooajovr7ph4/mnIDpq5jnmoR0b3A1CiMjIyBsb2dmYy50aHJlc2hvbGQgPSAwLjUsIG1pbi5kaWZmLnBjdCA9IDAuMyBwY3QuMT4wLjcKZGF0YXNldDIKYGBge3J9CkNBX2RhdGFzZXQyX21hcmtlcnMgPC0gRmluZEFsbE1hcmtlcnMoQ0FfZGF0YXNldDIsIGxvZ2ZjLnRocmVzaG9sZCA9IDAuNSwgbWluLmRpZmYucGN0ID0gMC4zLCBvbmx5LnBvcyA9IFQpCkNBX2RhdGFzZXQyX21hcmtlcnMgPC0gQ0FfZGF0YXNldDJfbWFya2Vyc1tDQV9kYXRhc2V0Ml9tYXJrZXJzJHBjdC4xPjAuNyxdICU+JSBncm91cF9ieShjbHVzdGVyKSAKCmdlbmVzX3RvX3Nob3cgPC0gQ0FfZGF0YXNldDJfbWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHNsaWNlX21heChuID0gNSwgb3JkZXJfYnkgPSBhdmdfbG9nRkMpCgpzdmcocGFzdGUwKCJDQV9kYXRhc2V0Ml9zdXBwIiwiX21hcmtlcnMuc3ZnIiksIGhlaWdodCA9IDEwLCB3aWR0aCA9IDE1KQpkaG0yKENBX2RhdGFzZXQyX21hcmtlcnMkZ2VuZSwgQ0FfZGF0YXNldDIsIGdlbmVzX3RvX3Nob3ckZ2VuZSwiQ0FfZGF0YXNldDJfc3VwcCIpCmRldi5vZmYoKQpgYGAKZGF0YXNldDEKYGBge3J9CkNBX2RhdGFzZXQxX21hcmtlcnMgPC0gRmluZEFsbE1hcmtlcnMoQ0FfZGF0YXNldDEsIGxvZ2ZjLnRocmVzaG9sZCA9IDAuNSwgbWluLmRpZmYucGN0ID0gMC4zLCBvbmx5LnBvcyA9IFQpCkNBX2RhdGFzZXQxX21hcmtlcnMgPC0gQ0FfZGF0YXNldDFfbWFya2Vyc1tDQV9kYXRhc2V0MV9tYXJrZXJzJHBjdC4xPjAuNyxdICU+JSBncm91cF9ieShjbHVzdGVyKSAKCmdlbmVzX3RvX3Nob3cgPC0gQ0FfZGF0YXNldDFfbWFya2VycyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHNsaWNlX21heChuID0gNSwgb3JkZXJfYnkgPSBhdmdfbG9nRkMpCgpzdmcocGFzdGUwKCJDQV9kYXRhc2V0MV9zdXBwIiwiX21hcmtlcnMuc3ZnIiksIGhlaWdodCA9IDEwLCB3aWR0aCA9IDE1KQpkaG0yKENBX2RhdGFzZXQxX21hcmtlcnMkZ2VuZSwgQ0FfZGF0YXNldDEsIGdlbmVzX3RvX3Nob3ckZ2VuZSwiQ0FfZGF0YXNldDFfc3VwcCIpCmRldi5vZmYoKQpgYGAKCgpkYXRhc2V0MApgYGB7cn0KaHVtYW5fY29yb25hcnlfbWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhodW1hbl9jb3JvbmFyeSwgbG9nZmMudGhyZXNob2xkID0gMC41LCBtaW4uZGlmZi5wY3QgPSAwLjMsIG9ubHkucG9zID0gVCkKaHVtYW5fY29yb25hcnlfbWFya2VycyA8LSBodW1hbl9jb3JvbmFyeV9tYXJrZXJzW2h1bWFuX2Nvcm9uYXJ5X21hcmtlcnMkcGN0LjE+MC43LF0gJT4lIGdyb3VwX2J5KGNsdXN0ZXIpIAoKZ2VuZXNfdG9fc2hvdyA8LSBodW1hbl9jb3JvbmFyeV9tYXJrZXJzICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgc2xpY2VfbWF4KG4gPSA1LCBvcmRlcl9ieSA9IGF2Z19sb2dGQykKCnN2ZyhwYXN0ZTAoImh1bWFuX2Nvcm9uYXJ5X3N1cHAiLCJfbWFya2Vycy5zdmciKSwgaGVpZ2h0ID0gMTAsIHdpZHRoID0gMTUpCmRobTIoaHVtYW5fY29yb25hcnlfbWFya2VycyRnZW5lLCBodW1hbl9jb3JvbmFyeSwgZ2VuZXNfdG9fc2hvdyRnZW5lLCJodW1hbl9jb3JvbmFyeV9zdXBwIikKZGV2Lm9mZigpCmBgYAojIOagt+acrOe7huiDnuavlOS+iwpgYGB7cn0KSWRlbnRzKGh1bWFuX2Nvcm9uYXJ5KSA8LSBodW1hbl9jb3JvbmFyeSRjb25kaXRpb25zCnNwMSA8LSBzdWJzZXQoaHVtYW5fY29yb25hcnksIGlkZW50cyA9ICJzYW1wbGUxIikKc3AyIDwtIHN1YnNldChodW1hbl9jb3JvbmFyeSwgaWRlbnRzID0gInNhbXBsZTIiKQpzcDMgPC0gc3Vic2V0KGh1bWFuX2Nvcm9uYXJ5LCBpZGVudHMgPSAic2FtcGxlMyIpCnNwNCA8LSBzdWJzZXQoaHVtYW5fY29yb25hcnksIGlkZW50cyA9ICJzYW1wbGU0IikKcHJvcF9tYXQgPC0gY2JpbmQocHJvcC50YWJsZSh0YWJsZShzcDEkQ2xhc3NpZmljYXRpb24xKSkscHJvcC50YWJsZSh0YWJsZShzcDIkQ2xhc3NpZmljYXRpb24xKSkpCnByb3BfbWF0MiA8LSBjYmluZChwcm9wLnRhYmxlKHRhYmxlKHNwMyRDbGFzc2lmaWNhdGlvbjEpKSxwcm9wLnRhYmxlKHRhYmxlKHNwNCRDbGFzc2lmaWNhdGlvbjEpKSkKcHJvcF9tYXQgPC0gY2JpbmQocHJvcF9tYXQsIHByb3BfbWF0MikKY29sbmFtZXMocHJvcF9tYXQpIDwtIGxldmVscyhJZGVudHMoaHVtYW5fY29yb25hcnkpKQoKCnBsb3RfZGF0YSA9IG1lbHQocHJvcF9tYXQpCmNvbG5hbWVzKHBsb3RfZGF0YSkgPSBjKCdjZWxsIHR5cGUnLCdwb3NpdGlvbicsJ3Byb3BvcnRpb24nKSPkv67mlLnmr4/kuIDliJfnmoTlkI3np7AKCmdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0gYGNlbGwgdHlwZWAsIHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gcG9zaXRpb24pKSArIAogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHdpZHRoPTAuNSkgKyB0aGVtZV9idygpCgpwcm9wX3Bsb3QgPC0gZ2dwbG90KHBsb3RfZGF0YSwgYWVzKHggPSBgY2VsbCB0eXBlYCwgeSA9IHByb3BvcnRpb24sIGZpbGwgPSBwb3NpdGlvbikpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScsIHBvc2l0aW9uID0gImRvZGdlIiwgd2lkdGg9MC43KSArIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDAuMykpKwogIHRoZW1lX2J3KCkgKyBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLDApKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yc19saXN0WzM6Nl0pICt0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIGNvbG91ciA9ICJibGFjayIpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwgY29sb3VyID0gImJsYWNrIiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkpCgpnZ3NhdmUoImh1bWFuX2Nvcm9uYXJ5X3Byb3Auc3ZnIiwgZGV2aWNlID0gc3ZnLCBwbG90ID0gcHJvcF9wbG90LCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA2KQoKYGBgCgoKYGBge3J9CklkZW50cyhDQV9kYXRhc2V0MSkgPC0gQ0FfZGF0YXNldDEkb3JpZy5pZGVudApJZGVudHMoQ0FfZGF0YXNldDEpIDwtIGMoInNhbXBsZTEiLCJzYW1wbGUyIiwic2FtcGxlMyIpCgpzcDEgPC0gc3Vic2V0KENBX2RhdGFzZXQxLCBpZGVudHMgPSAic2FtcGxlMSIpCnNwMiA8LSBzdWJzZXQoQ0FfZGF0YXNldDEsIGlkZW50cyA9ICJzYW1wbGUyIikKc3AzIDwtIHN1YnNldChDQV9kYXRhc2V0MSwgaWRlbnRzID0gInNhbXBsZTMiKQpwcm9wX21hdCA8LSBjYmluZChwcm9wLnRhYmxlKHRhYmxlKHNwMSRDbGFzc2lmaWNhdGlvbjEpKSxwcm9wLnRhYmxlKHRhYmxlKHNwMiRDbGFzc2lmaWNhdGlvbjEpKSxwcm9wLnRhYmxlKHRhYmxlKHNwMyRDbGFzc2lmaWNhdGlvbjEpKSkKCmNvbG5hbWVzKHByb3BfbWF0KSA8LSBsZXZlbHMoSWRlbnRzKENBX2RhdGFzZXQxKSkKCgpwbG90X2RhdGEgPSBtZWx0KHByb3BfbWF0KQpjb2xuYW1lcyhwbG90X2RhdGEpID0gYygnY2VsbCB0eXBlJywncG9zaXRpb24nLCdwcm9wb3J0aW9uJykj5L+u5pS55q+P5LiA5YiX55qE5ZCN56ewCgpnZ3Bsb3QocGxvdF9kYXRhLCBhZXMoeCA9IGBjZWxsIHR5cGVgLCB5ID0gcHJvcG9ydGlvbiwgZmlsbCA9IHBvc2l0aW9uKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JywgcG9zaXRpb24gPSAiZG9kZ2UiLCB3aWR0aD0wLjUpICsgdGhlbWVfYncoKQoKcHJvcF9wbG90IDwtIGdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0gYGNlbGwgdHlwZWAsIHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gcG9zaXRpb24pKSArIAogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHdpZHRoPTAuNykgKyBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwwLjYpKSsKICB0aGVtZV9idygpICsgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwwKSkgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnNfbGlzdFszOjZdKSArdGhlbWUoCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LCBjb2xvdXIgPSAiYmxhY2siKSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIGNvbG91ciA9ICJibGFjayIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpKQoKZ2dzYXZlKCJDQV9kYXRhc2V0MV9wcm9wLnN2ZyIsIGRldmljZSA9IHN2ZywgcGxvdCA9IHByb3BfcGxvdCwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNikKYGBgCgoKIyMgWEdCb29zdCBmZWF0dXJlCiMjIyBwcmV0cmFpbiBBQy0tUEEKYGBge3IgZmlnLndpZHRoPTYsZmlnLmhlaWdodD02fQpmZWEgPC0gcmVhZC5jc3YoIi4vZGF0YXRhYmxlL0FDX2ZlYXR1cmVzLmNzdiIpCmdnb2JqIDwtIG11bHRpX2ZlYXR1cmVwbG90KGZlYSRGZWF0dXJlWzE6MTZdLGRzMl9BQyxsYWJlbHMgPSAiIixsYWJlbCA9IEYpCmdnc2F2ZSgiQUNwcmV0cmFpbl9mZWF0dXJlcy5wbmciLCBkZXZpY2UgPSBwbmcsIHBsb3QgPSBnZ29iaiwgd2lkdGggPSA4LCBoZWlnaHQgPSA4KQoKZmVhIDwtIHJlYWQuY3N2KCIuL2RhdGF0YWJsZS9QQV9mZWF0dXJlcy5jc3YiKQpnZ29iaiA8LSBtdWx0aV9mZWF0dXJlcGxvdChmZWEkRmVhdHVyZVsxOjE2XSxkczJfUEEsbGFiZWxzID0gIiIsbGFiZWwgPSBGKQpnZ3NhdmUoIlBBcHJldHJhaW5fZmVhdHVyZXMucG5nIiwgZGV2aWNlID0gcG5nLCBwbG90ID0gZ2dvYmosIHdpZHRoID0gOCwgaGVpZ2h0ID0gOCkKYGBgCgojIyMgbW9kZWwgQUMtLVBBCmBgYHtyIGZpZy53aWR0aD02LGZpZy5oZWlnaHQ9Nn0KZmVhIDwtIHJlYWQuY3N2KCIuL2RhdGF0YWJsZS9BQ3RyYWluX2ZlYXR1cmVzLmNzdiIpCmdnb2JqIDwtIG11bHRpX2ZlYXR1cmVwbG90KGZlYSRGZWF0dXJlWzE6MTZdLGRzMl9BQyxsYWJlbHMgPSAiIixsYWJlbCA9IEYpCmdnc2F2ZSgiQUNtb2RlbF9mZWF0dXJlcy5wbmciLCBkZXZpY2UgPSBwbmcsIHBsb3QgPSBnZ29iaiwgd2lkdGggPSA4LCBoZWlnaHQgPSA4KQoKZmVhIDwtIHJlYWQuY3N2KCIuL2RhdGF0YWJsZS9QQXRyYWluX2ZlYXR1cmVzLmNzdiIpCmdnb2JqIDwtIG11bHRpX2ZlYXR1cmVwbG90KGZlYSRGZWF0dXJlWzE6MTZdLGRzMl9QQSxsYWJlbHMgPSAiIixsYWJlbCA9IEYpCmdnc2F2ZSgiUEFtb2RlbF9mZWF0dXJlcy5wbmciLCBkZXZpY2UgPSBwbmcsIHBsb3QgPSBnZ29iaiwgd2lkdGggPSA4LCBoZWlnaHQgPSA4KQpgYGAKCiMjIyBtb2RlbCBkczIKYGBge3IgZmlnLndpZHRoPTYsZmlnLmhlaWdodD02fQpmZWEgPC0gcmVhZC5jc3YoIi4vZGF0YXRhYmxlL2RzMl9mZWF0dXJlcy5jc3YiKQpnZ29iaiA8LSBtdWx0aV9mZWF0dXJlcGxvdChmZWEkRmVhdHVyZVsxOjE2XSxkczIsbGFiZWxzID0gIiIsbGFiZWwgPSBGKQpnZ3NhdmUoImRzMm1vZGVsX2ZlYXR1cmVzLnBuZyIsIGRldmljZSA9IHBuZywgcGxvdCA9IGdnb2JqLCB3aWR0aCA9IDgsIGhlaWdodCA9IDgpCgpmZWEgPC0gcmVhZC5jc3YoIi4vZGF0YXRhYmxlL2RzMF9mZWF0dXJlcy5jc3YiKQpnZ29iaiA8LSBtdWx0aV9mZWF0dXJlcGxvdChmZWEkRmVhdHVyZVsxOjE2XSxkczAsbGFiZWxzID0gIiIsbGFiZWwgPSBGKQpnZ3NhdmUoImRzMG1vZGVsX2ZlYXR1cmVzLnBuZyIsIGRldmljZSA9IHBuZywgcGxvdCA9IGdnb2JqLCB3aWR0aCA9IDgsIGhlaWdodCA9IDgpCmBgYAoKCiMjIHNjYXR0ZXIg5q+U6L6DIGZpZy4zIERDTiDlkowgTFVNIOWcqCBGYk0g5LitIHN1cCB2cyB1bnN1cAojIyMgZHMyIC0+IGRzMApgYGB7cn0KYnN0X21vZGVsIDwtIHJlYWRSRFMoImRzMl9tb2RlbC5yZHMiKQpkczJfZGF0YSA8LSBnZXRfZGF0YV90YWJsZShkczIsIGhpZ2h2YXIgPSBGLCB0eXBlID0gImRhdGEiKQpJZGVudHMoZHMyKSA8LSBkczIkc2V1cmF0X2NsdXN0ZXJzCklkZW50cyhkczApIDwtIGRzMCRzZXVyYXRfY2x1c3RlcnMKdGVtcCA8LSBnZXRfZGF0YV90YWJsZShkczAsIGhpZ2h2YXIgPSBGLCB0eXBlID0gImRhdGEiKQpkczBfZGF0YSA8LSBtYXRyaXgoZGF0YT0wLCBucm93ID0gbGVuZ3RoKHJvd25hbWVzKGRzMl9kYXRhKSksIG5jb2wgPSBsZW5ndGgoY29sbmFtZXModGVtcCkpLCAKICAgICAgICAgICAgICAgICAgIGJ5cm93ID0gRkFMU0UsIGRpbW5hbWVzID0gbGlzdChyb3duYW1lcyhkczJfZGF0YSksY29sbmFtZXModGVtcCkpKQpmb3IoaSBpbiBpbnRlcnNlY3Qocm93bmFtZXMoZHMyX2RhdGEpLCByb3duYW1lcyh0ZW1wKSkpewogIGRzMF9kYXRhW2ksXSA8LSB0ZW1wW2ksXQp9CnJtKHRlbXApCmRzMF9sYWJlbCA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihJZGVudHMoZHMwKSkpCmNvbG5hbWVzKGRzMF9kYXRhKSA8LSBOVUxMCmRzMF90ZXN0X2RhdGEgPC0gbGlzdChkYXRhID0gdChhcyhkczBfZGF0YSwiZGdDTWF0cml4IikpLCBsYWJlbCA9IGRzMF9sYWJlbCkKZHMwX3Rlc3QgPC0geGdiLkRNYXRyaXgoZGF0YSA9IGRzMF90ZXN0X2RhdGEkZGF0YSxsYWJlbCA9IGRzMF90ZXN0X2RhdGEkbGFiZWwpCgoj6aKE5rWL57uT5p6cCnByZWRpY3RfZHMwX3Rlc3QgPC0gcHJlZGljdChic3RfbW9kZWwsIG5ld2RhdGEgPSBkczBfdGVzdCkKcHJlZGljdF9wcm9wX2RzMCA8LSBtYXRyaXgoZGF0YT1wcmVkaWN0X2RzMF90ZXN0LCBucm93ID0gbGVuZ3RoKGxldmVscyhJZGVudHMoZHMyKSkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IG5jb2woZHMwKSwgYnlyb3cgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbW5hbWVzID0gbGlzdChsZXZlbHMoSWRlbnRzKGRzMikpLGNvbG5hbWVzKGRzMCkpKQoKIyMg5b6X5Yiw5YiG576k57uT5p6cCmRzMF9yZXMgPC0gYXBwbHkocHJlZGljdF9wcm9wX2RzMCwyLGZ1bmMscm93bmFtZXMocHJlZGljdF9wcm9wX2RzMCkpCklkZW50cyhkczApIDwtIGZhY3RvcihkczBfcmVzLGxldmVscyA9IGMoMDo0KSkKdW1hcHBsb3QoZHMwKQpkczAkc3VwY2x1c3RlcmluZyA8LSBJZGVudHMoZHMwKSAj5L+d5a2Y55uR552j6IGa57G757uT5p6cCmBgYAoKYGBge3J9CklkZW50cyhkczApIDwtIGRzMCRzdXBjbHVzdGVyaW5nCnN1cF9kczBGQk0gPC0gc3Vic2V0KGRzMCwgaWRlbnQgPSAiMSIpCklkZW50cyhkczApIDwtIGRzMCRDbGFzc2lmaWNhdGlvbjEKdW5zdXBfZHMwRkJNIDwtIHN1YnNldChkczAsIGlkZW50ID0gIkZpYnJvbXlvY3l0ZSIpCgpkYXRhMSA8LSBGZXRjaERhdGEob2JqZWN0ID0gc3VwX2RzMEZCTSwgdmFycyA9IGMoIkxVTSIsICJEQ04iKSkKcm93bmFtZXMoZGF0YTEpIDwtICBOVUxMCmRhdGExJGdyb3VwIDwtICJzdXAiCgpkYXRhMiA8LSBGZXRjaERhdGEob2JqZWN0ID0gdW5zdXBfZHMwRkJNLCB2YXJzID0gYygiTFVNIiwgIkRDTiIpKQpyb3duYW1lcyhkYXRhMikgPC0gIE5VTEwKZGF0YTIkZ3JvdXAgPC0gInVuc3VwIgoKZGF0YSA8LSByYmluZChkYXRhMSxkYXRhMikKCmdncGxvdChkYXRhLCBhZXMoeD1MVU0sIHk9RENOLCBjb2xvciA9IGdyb3VwLCBncm91cCA9IGdyb3VwKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtICwgY29sb3I9InJlZCIsIGZpbGw9IiM2OWIzYTIiLCBzZT1UUlVFKSArCiAgdGhlbWVfY2xhc3NpYygpICsgIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCxjb2xvciA9ICJibGFjayIpLAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShzaXplID0gMSksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShzaXplID0gMSksCiAgICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSkKCmBgYAoKCgpgYGB7cn0KSWRlbnRzKGRzMikgPC0gZHMyJENsYXNzaWZpY2F0aW9uMQpkczJfU01DMiA8LSBzdWJzZXQoZHMyLCBpZGVudCA9ICJTTUMyIikKCgpkYXRhMiA8LSBGZXRjaERhdGEob2JqZWN0ID0gZHMyX1NNQzIsIHZhcnMgPSBjKCJBQ1RBMiIsICJUQUdMTiIpKQpyb3duYW1lcyhkYXRhMikgPC0gIE5VTEwKZGF0YTIkZ3JvdXAgPC0gInVuc3VwIgoKZ2dwbG90KGRhdGEyLCBhZXMoeD1BQ1RBMiwgeT1UQUdMTiwgY29sb3IgPSBncm91cCwgZ3JvdXAgPSBncm91cCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAzLGFscGhhPTAuMSkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9bG0gLCBjb2xvcj0icmVkIiwgZmlsbD0iIzY5YjNhMiIsIGZvcm11bGEgPSAneX54Jywgc2U9VFJVRSkgKwogIHRoZW1lX2NsYXNzaWMoKSArICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCxjb2xvciA9ICJibGFjayIpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsY29sb3IgPSAiYmxhY2siKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDEpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDEpLAogICAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCkpCgpkYXRhMiA8LSBGZXRjaERhdGEob2JqZWN0ID0gZHMyX1NNQzIsIHZhcnMgPSBjKCJTT1NUIiwgIkRMWDUiKSkKcm93bmFtZXMoZGF0YTIpIDwtICBOVUxMCmRhdGEyJGdyb3VwIDwtICJ1bnN1cCIKCmdncGxvdChkYXRhMiwgYWVzKHg9U09TVCwgeT1ETFg1LCBjb2xvciA9IGdyb3VwLCBncm91cCA9IGdyb3VwKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsYWxwaGE9MC4xKSArIAogIGdlb21fc21vb3RoKG1ldGhvZD1sbSAsIGNvbG9yPSJyZWQiLCBmaWxsPSIjNjliM2EyIiwgZm9ybXVsYSA9ICd5fngnLCBzZT1UUlVFKSArCiAgdGhlbWVfY2xhc3NpYygpICsgIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCxjb2xvciA9ICJibGFjayIpLAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShzaXplID0gMSksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShzaXplID0gMSksCiAgICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSkKYGBgCmBgYHtyfQojIGRpbShzdWJzZXQoZHMyX1NNQzIsIFNPU1Q+MCkpWzJdCgpkaW0oc3Vic2V0KGRzMl9TTUMyLCBgRExYNWA+MSkpWzJdCgpkaW0oc3Vic2V0KGRzMl9TTUMyLCBgRExYNWA+MSZTT1NUPjEpKVsyXQoKcHJpbnQoIi4uLiIpCmRpbShzdWJzZXQoZHMyX1NNQzIsIERMWDU+MSkpWzJdCgpkaW0oc3Vic2V0KGRzMl9TTUMyLCBgUFJETTZgPjEpKVsyXQoKZGltKHN1YnNldChkczJfU01DMiwgYFBSRE02YD4xJkRMWDU+MSkpWzJdCmBgYApgYGB7cn0KZGltKHN1YnNldChkczJfU01DMiwgQUNUQTI+MSkpWzJdCgpkaW0oc3Vic2V0KGRzMl9TTUMyLCBUQUdMTj4xKSlbMl0KCmRpbShzdWJzZXQoZHMyX1NNQzIsIFRBR0xOPjEmQUNUQTI+MSkpWzJdCmBgYAoKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLgoKV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDdHJsK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuCgpUaGUgcHJldmlldyBzaG93cyB5b3UgYSByZW5kZXJlZCBIVE1MIGNvcHkgb2YgdGhlIGNvbnRlbnRzIG9mIHRoZSBlZGl0b3IuIENvbnNlcXVlbnRseSwgdW5saWtlICpLbml0KiwgKlByZXZpZXcqIGRvZXMgbm90IHJ1biBhbnkgUiBjb2RlIGNodW5rcy4gSW5zdGVhZCwgdGhlIG91dHB1dCBvZiB0aGUgY2h1bmsgd2hlbiBpdCB3YXMgbGFzdCBydW4gaW4gdGhlIGVkaXRvciBpcyBkaXNwbGF5ZWQuCg==